﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Mvc;
using MyWeb.Common.Helper;
using MyWeb.Common.MemoryCache;
using MyWeb.Extensions.ServiceExtensions.Authorization;
using MyWeb.Model;
using MyWeb.Repository.UnitOfWorks;
using MyWeb.Services;
using MyWeb.Services.RolePermission;
using Newtonsoft.Json.Linq;
using SqlSugar;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using MyWeb.Services.Base;
using MyWeb.Model.User;
using MyWeb.Extensions.ServiceExtensions.Swagger;
using static MyWeb.Extensions.ServiceExtensions.Swagger.CustomApiVersion;
using MyWeb.Model.Models;

namespace MyWeb.Api.Controllers.V1.System
{
    /// <summary>
    /// 登录管理【无权限】
    /// </summary>
    [Produces("application/json")]
    [CustomRoute(ApiVersions.V1)]
    [AllowAnonymous]
    public class LoginController : BaseController
    {



        readonly ISysUserInfoServices _sysUserInfoServices;
        private readonly SqlSugarScope _dbBase;
        private readonly ICaching _cache;
        readonly PermissionRequirement _requirement;
        private readonly IRoleModulePermissionServices _roleModulePermissionServices;
        private readonly JwtSecurityTokenHandler _jwtSecurityTokenHandler;
        private readonly IBaseServices<Permission> _baseServices;
        private readonly IBaseServices<SysUserInfo> _baseUserServices;

        #region 构造函数
        /// <summary>
        /// 通过构造函数获取注入实例
        /// </summary>
        /// <param name="sysUserInfoServices"></param>
        /// <param name="unitOfWorkManage"></param>
        /// <param name="cache"></param>
        /// <param name="requirement"></param>
        /// <param name="roleModulePermissionServices"></param>
        /// <param name="jwtSecurityTokenHandler"></param>
        /// <param name="baseServices"></param>
        /// <param name="baseUserServices"></param>
        public LoginController(
            ISysUserInfoServices sysUserInfoServices,
            IUnitOfWorkManage unitOfWorkManage,
            ICaching cache,
            PermissionRequirement requirement,
            IRoleModulePermissionServices roleModulePermissionServices,
            JwtSecurityTokenHandler jwtSecurityTokenHandler,
            IBaseServices<Permission> baseServices,
            IBaseServices<SysUserInfo> baseUserServices
            )
        {
            _sysUserInfoServices = sysUserInfoServices;
            _dbBase = unitOfWorkManage.GetDbClient();
            _cache = cache;
            _requirement = requirement;
            _roleModulePermissionServices = roleModulePermissionServices;
            _jwtSecurityTokenHandler = jwtSecurityTokenHandler;
            _baseServices = baseServices;
            _baseUserServices = baseUserServices;
        }
        #endregion

        /// <summary>
        /// 测试-获取Token
        /// </summary>
        /// <param name="name"></param>
        /// <param name="pass"></param>
        /// <returns></returns>
        [HttpGet]
        public ApiResult GetJwtStr(string name = "admin", string pass = "admin")
        {
            string jwtStr = string.Empty;
            bool suc = false;

            //var user = await _sysUserInfoServices.Query();

            //var str = _dbBase.Ado.GetDataTable("SELECT * FROM dbo.Modules");

            //string str = MD5Helper.MD5Encrypt32(pass);
            if (name == "admin" && pass == "admin")
            {
                TokenModelJwt tokenModel = new TokenModelJwt { Uid = 1, Role = name };

                jwtStr = JwtHelper.IssueJwt(tokenModel);
                _cache.Set("newjwttoken", jwtStr, 30);
                suc = true;
            }
            else
            {
                jwtStr = "login fail!!!";
            }

            return new ApiResult()
            {
                Success = suc,
                Msg = suc ? "获取成功" : "获取失败",
                Response = jwtStr
            };
        }



        /// <summary>
        /// 获取JWT的方法3：整个系统主要方法
        /// </summary>
        /// <param name="name"></param>
        /// <param name="pass"></param>
        /// <returns></returns>
        [HttpGet]
        [ActionName("JWTToken3.0")]
        public async Task<ApiResult> GetJwtToken3(string name = "admins", string pass = "admins")
        {
            string jwtStr = string.Empty;

            if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(pass))
                return Failed<TokenInfoViewModel>(null,msg:"用户名或密码不能为空");

            pass = MD5Helper.MD5Encrypt32(pass);

            var user = await _baseUserServices.Query(d => d.LoginName == name && d.LoginPWD == pass && d.IsDeleted == false);
            if (user.Count > 0)
            {
                var userRoles = await _sysUserInfoServices.GetUserRoleNameStr(name, pass);
                //如果是基于用户的授权策略，这里要添加用户;如果是基于角色的授权策略，这里要添加角色
                var claims = new List<Claim> {
                    new Claim(ClaimTypes.Name, name),
                    new Claim(JwtRegisteredClaimNames.Jti, user.FirstOrDefault().Id.ToString()),
                    new Claim(JwtRegisteredClaimNames.Iat, DateTime.Now.ToString()),
                    new Claim(ClaimTypes.Expiration, DateTime.Now.AddSeconds(_requirement.Expiration * 60).ToString()) };
                claims.AddRange(userRoles.Split(',').Select(s => new Claim(ClaimTypes.Role, s)));


                // ids4和jwt切换
                // jwt
                #pragma warning disable CS8604 // 引用类型参数可能为 null。
                if (!AppSettings.app(sections: new string[] { "Startup", "IdentityServer4", "Enabled" }).ObjToBool())
                {
                    var data = await _roleModulePermissionServices.RoleModuleMaps();
                    var list = (from item in data
                                where item.IsDeleted == false
                                orderby item.Id
                                select new PermissionItem
                                {
                                    Url = item.Module?.LinkUrl,
                                    Role = item.Role?.Name.ObjToString(),
                                }).ToList();

                    _requirement.Permissions = list;
                }
                #pragma warning restore CS8604 // 引用类型参数可能为 null。
                JwtToken jwtToken = new JwtToken(_cache, _jwtSecurityTokenHandler);
                var token = jwtToken.BuildJwtToken(claims.ToArray(), _requirement);
                return Success(token, "获取成功");
            }
            else
            {
                return Failed<TokenInfoViewModel>(null,"认证失败");
            }
        }



        /// <summary>
        /// 请求刷新Token（以旧换新）
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<ApiResult> RefreshToken(string token = "")
        {
            string jwtStr = string.Empty;

            if (string.IsNullOrEmpty(token))
                return Failed<TokenInfoViewModel>(null,"token无效，请重新登录！");
            var tokenModel = JwtHelper.SerializeJwt(token);
            if (tokenModel != null && JwtHelper.customSafeVerify(token) && tokenModel.Uid > 0)
            {
                var user = await _baseUserServices.QueryById(tokenModel.Uid);
                var value = User.Claims.SingleOrDefault(s => s.Type == JwtRegisteredClaimNames.Iat)?.Value;
                if (value != null && user.CriticalModifyTime > value.ObjToDate())
                {
                    return Failed<TokenInfoViewModel>(null,"很抱歉,授权已失效,请重新授权！");
                }

                if (user != null && !(value != null && user.CriticalModifyTime > value.ObjToDate()))
                {
                    var userRoles = await _sysUserInfoServices.GetUserRoleNameStr(user.LoginName, user.LoginPWD);
                    //如果是基于用户的授权策略，这里要添加用户;如果是基于角色的授权策略，这里要添加角色
                    var claims = new List<Claim> {
                    new Claim(ClaimTypes.Name, user.LoginName),
                    new Claim(JwtRegisteredClaimNames.Jti, tokenModel.Uid.ObjToString()),
                    new Claim(JwtRegisteredClaimNames.Iat, DateTime.Now.ToString()),
                    new Claim(ClaimTypes.Expiration, DateTime.Now.AddSeconds(_requirement.Expiration * 60).ToString()) };
                    claims.AddRange(userRoles.Split(',').Select(s => new Claim(ClaimTypes.Role, s)));

                    //用户标识
                    var identity = new ClaimsIdentity(JwtBearerDefaults.AuthenticationScheme);
                    identity.AddClaims(claims);
                    JwtToken jwtToken = new JwtToken(_cache, _jwtSecurityTokenHandler);
                    var refreshToken = jwtToken.BuildJwtToken(claims.ToArray(), _requirement);
                    return Success(refreshToken, "获取成功");
                }
            }
            return Failed<TokenInfoViewModel>(null,"认证失败！");
        }

    }
}
